aws-actions/configure-aws-credentialsがOIDCプロバイダを介したSwitchRoleに対応していたので実装を辿ってみた
先日注目が集まった、OIDCプロバイダを用いることによって実現した AWS Credentials 不要でのSwitchRole は記憶に新しいところです。ただ、正直どうやって業務利用すべきかというところでした。肝のWebIdentityTokenの扱いに困ったわけです。
そして先程GitHub ActionsでAWSを使う際に必須とも言える aws-actions/configure-aws-credentials のREADMEを見ていたところ、OIDCを用いたSwitchRoleの仕組みが追加されていました。
特にニュースとして上がっているわけではなく、いつの間に、といった感想です。同様の速報記事は多数上がるだろうと想定の元、ではどういった形で入っているのか辿ってみました。
Actionsへの変更詳細
追加は以下のPRによるものです。
WebIdentityTokenについて、特にリクエストしているコードがありません。aws-actions/configure-aws-credentials ではこのパラメータを他のライブラリから取得しています。 actions/toolkit
です。
actions/toolkitからのToken取得
AssumeRoleWithWebIdentityは以下のパラメータを揃えてリクエストを行う必要があります。
- DurationSeconds
- Policy
- PolicyArns.member.N
- ProviderId
- RoleArn
- RoleSessionName
- WebIdentityToken
他のパラメータを見る限り、やはりネックはWebIdentityToken 1点。実際の取得過程を見ていきます。
先ず ACTIONS_ID_TOKEN_REQUEST_TOKEN
と ACTIONS_ID_TOKEN_REQUEST_URL
がGitHub Actions実行時に環境変数へセットされているようですが、この2つの環境変数に関した公式ドキュメントは見当たらず。
private static getRequestToken(): string { const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] if (!token) { throw new Error( 'Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable' ) } return token } private static getIDTokenUrl(): string { const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL'] if (!runtimeUrl) { throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable') } return runtimeUrl }
次に ACTIONS_ID_TOKEN_REQUEST_TOKEN
を Header にセットしつつ、ACTIONS_ID_TOKEN_REQUEST_URL
へリクエスト。
return new HttpClient( 'actions/oidc-client', [new BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions )
返ってきたtokenが WebIdentityToken
として利用されることになります。
static async getIDToken(audience?: string): Promise<string> { try { // New ID Token is requested from action service let id_token_url: string = OidcClient.getIDTokenUrl() if (audience) { const encodedAudience = encodeURIComponent(audience) id_token_url = `${id_token_url}&audience=${encodedAudience}` } debug(`ID token url is ${id_token_url}`) const id_token = await OidcClient.getCall(id_token_url) setSecret(id_token) return id_token } catch (error) { throw new Error(`Error message: ${error.message}`) } }
実装としては動くのですが、肝心の2つの環境変数については特にコメント等もないという状態でした。
あとがき
OIDCプロバイダを使った、認証不要になるという点で驚かせてくれた以下記事ですが、問題は $ACTIONS_ID_TOKEN_REQUEST_TOKEN
と $ACTIONS_ID_TOKEN_REQUEST_URL
の2点が不明瞭であること。
既にMarketPlace上ではOIDCプロバイダを前提とした認証でサンプルも掲載されています。正直もやっとしますが、動作に問題がなければ差し替えておくことでアクセスキー漏洩の心配も減りそうです。